/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor. 
 */
package cz.muni.fi.pv168.reminder.swing;

import cz.muni.fi.pv168.reminder.entities.Task;
import cz.muni.fi.pv168.reminder.entities.Worker;
import cz.muni.fi.pv168.reminder.managers.AssignmentManager;
import cz.muni.fi.pv168.reminder.managers.TaskManager;
import cz.muni.fi.pv168.reminder.managers.WorkerManager;
import cz.muni.fi.pv168.reminder.managers.implementation.AssignmentManagerImpl;
import cz.muni.fi.pv168.reminder.managers.implementation.TaskManagerImpl;
import cz.muni.fi.pv168.reminder.swing.DialogMainWorker.TableWorkerModel;
import cz.muni.fi.pv168.reminder.swing.workers.GetWorkerSwingWorker;
import cz.muni.fi.pv168.reminder.swing.workers.LoadWorkersSwingWorker;
import cz.muni.fi.pv168.reminder.swing.workers.UpdateWorkerSwingWorker;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.RowSorter;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import org.apache.commons.dbcp.BasicDataSource;

/**
 *
 * @author Adic
 */
public class DialogMainWorker extends javax.swing.JDialog {

    private static final Logger logger = Logger.getLogger("Reminder"); //NOI18N
    private static BasicDataSource dataSource = null;

    /**
     * Creates new form DialogMainWorker
     */
    public DialogMainWorker(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();

    }

    public static BasicDataSource getDataSource() {
        if (dataSource == null) {
            dataSource = new BasicDataSource();
            Properties prop = new Properties();
            InputStream is = WorkerManager.class.getResourceAsStream("jdbc.properties"); //NOI18N

            try {
                prop.load(is);
                is.close();
            } catch (IOException e) {
                logger.log(Level.SEVERE, "Can't load dataSource.", e); //NOI18N
                return null;
            }

            dataSource.setUsername(prop.getProperty("user")); //NOI18N 
            dataSource.setPassword(prop.getProperty("pass")); //NOI18N
            dataSource.setUrl(prop.getProperty("url")); //NOI18N
        }

        return dataSource;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jButton3 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("cz/muni/fi/pv168/reminder/swing/Strings"); // NOI18N
        jButton1.setText(bundle.getString("ADD WORKER")); // NOI18N
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jButton2.setText(bundle.getString("EDIT")); // NOI18N
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jTable1.setModel(new TableWorkerModel());
        jTable1.setRowSorter(new TableRowSorter<>(new TableWorkerModel()));
        jScrollPane1.setViewportView(jTable1);

        jButton3.setText(bundle.getString("CLOSE")); // NOI18N
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(24, 24, 24)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 347, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jButton1)
                        .addGap(48, 48, 48)
                        .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 89, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addGap(25, 25, 25))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(35, 35, 35)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton2)
                    .addComponent(jButton3))
                .addGap(26, 26, 26)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 316, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(31, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        DialogAddWorker addWorker = new DialogAddWorker(null, Boolean.TRUE);
        addWorker.pack();
        addWorker.setVisible(Boolean.TRUE);

        Worker worker = addWorker.getWorker();
        if (worker != null) {
            AddWorkerSwingWorker addWorkerSwingWorker = new AddWorkerSwingWorker(worker);
            addWorkerSwingWorker.execute();
            try {
                addWorkerSwingWorker.get();
                Logger.getLogger("Reminder").info("Worker " + worker + " created."); //NOI18N //NOI18N
            } catch (InterruptedException | ExecutionException ex) {
                Logger.getLogger("Reminder").log(Level.SEVERE, "Failed to create worker " + worker, ex); //NOI18N //NOI18N
            }
        }
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        if (jTable1.getSelectedRow() == -1) {
            return;
        }
        Worker worker = ((TableWorkerModel) jTable1.getModel()).getWorkerAtRow(jTable1.convertRowIndexToModel(jTable1.getSelectedRow()));
        if (worker == null) {
            return;
        }
        DialogWorkerDetail workerDetailDialog = new DialogWorkerDetail(this, true, worker.getId());

        workerDetailDialog.pack();
        workerDetailDialog.setVisible(Boolean.TRUE);

        Worker returnedWorker = workerDetailDialog.getWorker();

        ((TableWorkerModel) jTable1.getModel()).update(returnedWorker);

    }//GEN-LAST:event_jButton2ActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        setVisible(false);
    }//GEN-LAST:event_jButton3ActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) { //NOI18N
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(DialogMainWorker.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(DialogMainWorker.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(DialogMainWorker.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(DialogMainWorker.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the dialog */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                DialogMainWorker dialog = new DialogMainWorker(new javax.swing.JFrame(), true);
                dialog.addWindowListener(new java.awt.event.WindowAdapter() {
                    @Override
                    public void windowClosing(java.awt.event.WindowEvent e) {
                        System.exit(0);
                    }
                });
                dialog.setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    // End of variables declaration//GEN-END:variables

    public static class TableWorkerModel extends AbstractTableModel {

        private List<Worker> workers = new ArrayList<>();
        private LoadWorkersSwingWorker loadWorkersSwingWorker;
        private UpdateWorkerSwingWorker updateWorkerSwingWorker;
        private GetWorkerSwingWorker getWorkerSwingWorker;
        private AddWorkerSwingWorker addWorkerSwingWorker;

        public TableWorkerModel() {
            loadWorkers();
            fireTableDataChanged();
        }

        /**
         * Reloads tasks from DB
         */
        public void reload() {
            loadWorkers();
            fireTableDataChanged();
        }

        /**
         * Loads tasks from DB with filters
         */
        private void loadWorkers() {
            loadWorkersSwingWorker = new LoadWorkersSwingWorker();
            loadWorkersSwingWorker.execute();
            try {
                workers = loadWorkersSwingWorker.get();
                logger.info("Workers loaded successfully"); //NOI18N
            } catch (InterruptedException | ExecutionException ex) {
                logger.log(Level.SEVERE, "Can't load workers.", ex); //NOI18N
                DBError error = new DBError(null, true);
                error.pack();
                error.setVisible(true);
            }
            if (workers == null) {
                workers = new ArrayList<>();
            }
        }

        /**
         * Add task to db
         *
         * @param task
         */
        public void addWorker(Worker worker) {
            addWorkerSwingWorker = new AddWorkerSwingWorker(worker);
            addWorkerSwingWorker.execute();
            try {
                addWorkerSwingWorker.get();
                logger.info("Worker " + worker + " created"); //NOI18N
            } catch (InterruptedException | ExecutionException ex) {
                logger.log(Level.SEVERE, "Failed to create task " + worker, ex); //NOI18N
            }

        }

        public Worker getWorkerAtRow(int row) {
            if (row < 0 || row > workers.size() - 1) {
                return null;
            }
            return workers.get(row);
        }

        @Override
        public int getRowCount() {
            return workers.size();
        }

        @Override
        public int getColumnCount() {
            return 3;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            AssignmentManager aManager = new AssignmentManagerImpl();
            TaskManager taskManager = new TaskManagerImpl();
            aManager.setDataSource(FrameMainWindow.getDataSource());
            taskManager.setDataSource(getDataSource());
            Worker worker = workers.get(rowIndex);
            List<Task> tasks = taskManager.findAllPendingTasks();

            List<Task> allTasks = aManager.findTasksOfWorker(worker);
            int count = 0;
            for (Task task : allTasks) {
                if (tasks.contains(task)) {
                    count++;
                }
            }

            switch (columnIndex) {
                case 0:
                    return worker.getName();
                case 1:
                    return worker.getEmailAddress();
                case 2:
                    return count;

                default:
                    throw new IllegalArgumentException("column Index"); //NOI18N

            }
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            switch (columnIndex) {
                case 0:
                case 3:
                    return String.class;
                case 1:
                    return String.class;
                case 2:
                    return Integer.class;
                default:
                    throw new IllegalArgumentException("columnIndex");  //NOI18N
            }
        }

        @Override
        public String getColumnName(int column) {
            switch (column) {
                case 0:
                    return java.util.ResourceBundle.getBundle("cz/muni/fi/pv168/reminder/swing/Strings").getString("NAME");
                case 1:
                    return java.util.ResourceBundle.getBundle("cz/muni/fi/pv168/reminder/swing/Strings").getString("EMAIL");
                case 2:
                    return java.util.ResourceBundle.getBundle("cz/muni/fi/pv168/reminder/swing/Strings").getString("NUMBEROFTASKS");

                default:
                    throw new IllegalArgumentException("column Index"); //NOI18N

            }
        }

        /**
         * Return task from DB
         *
         * @param workerID
         * @return
         */
        Worker getWorker(Long workerID) {
            Worker worker = null;

            getWorkerSwingWorker = new GetWorkerSwingWorker(workerID);
            getWorkerSwingWorker.execute();
            try {
                worker = getWorkerSwingWorker.get();
                logger.info("Worker " + worker + "retrieved"); //NOI18N
            } catch (InterruptedException | ExecutionException ex) {
                logger.log(Level.SEVERE, "Failed to obtail task with id: " + workerID, ex); //NOI18N
                DBError error = new DBError(null, true);
                error.pack();
                error.setVisible(true);
            }
            return worker;
        }

        /**
         * Update task
         *
         * @param returnedTask
         */
        private void update(Worker returnedWorker) {
            updateWorkerSwingWorker = new UpdateWorkerSwingWorker(returnedWorker, this);
            updateWorkerSwingWorker.execute();
            try {
                updateWorkerSwingWorker.get();
                logger.info("Worker " + returnedWorker + " updated"); //NOI18N
            } catch (InterruptedException | ExecutionException ex) {
                logger.log(Level.SEVERE, "Failed to update task " + returnedWorker, ex); //NOI18N
            }
            reload();
        }
    }

 
}
